﻿ 
#include "stdafx.h"
#include "dict.h"
#include "functions.h"
#include "export_functions.h"



//=========================================================================
void dictLine::operator = (const char* line) throw(Error)
{
	if(!line) throw("line is NULL");
	const size_t LEN = strlen(line);
	if(LEN > MAX_WORD_LEN-1) 
	{
		throw Error("Big line lengh");
	}

	buf[0] = '\0';
	strncpy(buf, line, MAX_WORD_LEN-1);
}

bool dictLine::operator == (const char* aSource) const  throw(Error)
{
	std::string a = aSource;
	ksstr::toLower(a);

	return a == buf;
}

bool dictLine::operator < (const dictLine& a) const
{
	if( strcmp(buf, a.buf) < 0 ) return true;
	return false;
}









//=========================================================================

void dictionaryWord::writeToLine(std::string& dest) const
{
	dest = "";
	dest += this->english_word.c_str();
	dest += "=";

	for( int c=0; c<MAX_RUS_VARIANTS; c++ )
	{
		if(russians[c].empty() == false)
		{
			dest += russians[c].c_str();
			dest += "; ";
		}
	}

	
}


dictionaryWord::dictionaryWord(const std::string& line) throw(Error)
{
	reserved = 0;
	readFromLine(line);

}

void dictionaryWord::readFromLine(const std::string& line) throw(Error)
{
 
	if(line.length() == 0) throw Error("line is empty");

	// check line  prohibition symbols
	{
		for(size_t c=0; c<line.size(); c++)
		{
			if( line[c] == '\n' )
			{
				std::string temp;
				temp += "prohibition symbols is the line: ";
				temp += "(";
				temp += line;
				temp += ")";
				throw Error(temp.c_str() );
			}
		}

	}
	// end (check line  prohibition symbols)

	int separatorPos = -1;
	for(size_t c=0; c<line.size(); c++)	
	{
		if( line[c] == '=' )
		{
			separatorPos = (int)c;
			break;
		}
	}

	if(separatorPos == -1)
	{
		std::string temp;
		temp += "Separator position not found in the line ";
		temp += "(";
		temp += line;
		temp += ")";
		throw Error( temp.c_str() );
	}

	//	extract left and right
	{
		std::string left, right;
		left = line.substr(0, separatorPos);
		right = line.substr(separatorPos+1, line.length()-separatorPos);

		// assign eng word
		{
			left = ksstr::toLowerCopy(ksstr::trimCopy(left));
			this->english_word = left.c_str();

		}
		// end (assign eng word)

		// assign  russians
		{
			std::vector<std::string> lines;
			ksstr::splitTokens(lines, right, ";");

			if(lines.size() == 0)
			{
				std::string temp;
				temp += "russians part in line is empty ";
				temp += "(";
				temp += line;
				temp += ")";
				throw Error(temp.c_str() );
			}

			ksstr::removeEmptyLines(lines);
			ksstr::trimStrings(lines);
			for(size_t j=0; j<lines.size(); j++)
			{
				lines[j] = ksstr::toLowerCopy( lines[j] );
			}

			// check vector size
			if( lines.size() > MAX_RUS_VARIANTS )
			{
				std::string temp = "big nums rus items in the line (";
				temp += line;
				temp += ")";
				throw Error( temp.c_str() );
			}

			// copy
			for(size_t j=0; j<lines.size(); j++)
			{
				this->russians[j] = lines[j].c_str();
			}



		}
		// end (assign  russians)

	}
	// end (extract left and right)



	// ok!
}
	  



//=========================================================================
Dictionary::Dictionary(const std::wstring& fullpath) throw (Error)
{
	m_fullPath = fullpath;
	assert( m_fullPath.length() );

	try
	{
		std::string text;
		if(!ksstr::loadStrFromFileW(text, fullpath.c_str() ))
		{
			throw Error("В процессе загрузки словаря");
		}

		if( text.length() == 0 )
		{
			throw Error("Dictionary file is empty");
		}

		std::vector<std::string> veclines;
		ksstr::splitLines(veclines, text);
		ksstr::removeEmptyLines(veclines);

		for(size_t c=0; c<veclines.size(); c++)
		{
//			assert(false);
			try
			{
				dictionaryWord dw( veclines[c] );
				m_dictWords->push_back(dw);
			}
			catch(Error e)
			{
				std::string temp;  //xxxxxxxxxxxxxx
				temp += "Ошибка конструкции слова в словаре: ";
				temp += e.what();

				MessageError(temp);
				throw   e;
			}

		}



	}
	catch(Error err)
	{
		std::string temp;
		temp += "Ошибка загрузки словаря: ";
		temp += err.what();

		 MessageError(temp);
		 throw   err;
	}
	catch(...)
	{
		MessageError("Неизвестная ошибка загрузки словаря");
		CoreLogMessage("Exception:  Dictionary::Dictionary(const std::wstring& fullpath) throw (Error)\n");
	}

	CoreLogMessage("Load dict ok!  \n");


}

void Dictionary::Save()
{
	std::string text;

	// make text
	{
		std::string line;
		for(size_t c=0; c<m_dictWords->size(); c++)
		{
			m_dictWords->at(c).writeToLine(line);
			text += line;
			text += "\n";
		}

	}
	// end (make text)
			
	// save  ...
	if( !ksstr::saveStrToFileW( text, m_fullPath.c_str() ) )
	{
		throw Error("Error save distionary to file");
	}

}


size_t Dictionary::searchWordIndex(const char* engSource) const
{
	std::string eng = engSource;
	ksstr::toLower(eng);
	for(size_t c=0; c<m_dictWords->size(); c++)
	{
		if( m_dictWords->at(c).english_word == eng.c_str() )
		{
			return c;
		}
	}


	//assert(false);  return  0-1;
	//std::binary_search(  )
	// 
	return 0-1;
}

bool Dictionary::GetWorldInfoWord (char* dest_rus, const char* engWord)
{
	size_t index = searchWordIndex(engWord);
	if( 0-1 == index )
	{
		return false;
	}

	strcpy(dest_rus,  m_dictWords->at( index ).english_word.c_str());

	/*
	 
	// используем перебор 
	for(size_t c=0; c<m_dictWords.size(); c++)
	{
		if( strcmp(m_dictWords.at(c).english_word.c_str(), engWord) == 0 )
		{
			// нашли слово
			strcpy(dest_rus,  m_dictWords.at( (size_t)c ).english_word.c_str());
			return true;
		}
	}
	*/


    return false;
}

bool Dictionary::GetWorldInfoIndex(char* dest_eng, char* dest_rus, const int engWordIndex)
{
   if( (size_t)engWordIndex >= m_dictWords->size() )
   {
	   // нет такого слова
	   return false;
   }

   strcpy(dest_eng,  m_dictWords->at( (size_t)engWordIndex ).english_word.c_str() );

   char buf [1024];
   buf [0] = '\0';
   for(int c=0; c<dictionaryWord::MAX_RUS_VARIANTS; c++)
   {
	   if( m_dictWords->at( (size_t)engWordIndex ).russians[c].empty() == false )
	   {
		   strcat( buf,  m_dictWords->at( (size_t)engWordIndex ).russians[c].c_str() );
		   if( c != dictionaryWord::MAX_RUS_VARIANTS - 1 )
		   {
			   strcat(buf, "\n");
		   }
	   }
   }

   strcpy(dest_rus, buf );
   



	return true;
}

bool Dictionary::AddNewWord(const char* eng, const char* rus_lineSource)
{
	// используем перебор
	for(size_t c=0; c<m_dictWords->size(); c++)
	{
		if( strcmp(m_dictWords->at(c).english_word.c_str(), eng) == 0 )
		{
			// нашли слово
			//strcpy(dest_rus,  m_dictWords.at( (size_t)c ).english_word.c_str());
			return false;
		}
	}

	std::string line;
	line += eng;
	line += "=";

	// add russians
	{
		std::vector<std::string> lines;
		ksstr::splitLines(lines, std::string(rus_lineSource) );
		ksstr::trimStrings(lines);
		

		// add to line
		for(size_t c=0; c<lines.size(); c++)
		{
			line += lines[c];
			line += "; ";
		}

	}


	 

	try 
	{
		dictionaryWord dw(line);
		m_dictWords->push_back(dw);
		SortWords();
	}
	catch(Error e)
	{
		MessageError(e.what());
		return false;
	}
	



	return true;
}

bool Dictionary::ModifyWordIndex( const char* rus, const int engWordIndex )
{
	if( (size_t)engWordIndex >= m_dictWords->size() )
	{
		// нет такого слова
		return false;
	}

	std::vector<std::string> lines;
	ksstr::splitLines( lines,  std::string(rus) );
	ksstr::removeEmptyLines( lines );

	assert( lines.size() < dictionaryWord::MAX_RUS_VARIANTS  );

	// clear russians
	for(size_t c=0; c<dictionaryWord::MAX_RUS_VARIANTS; c++)
	{
		this->m_dictWords->at( (size_t)engWordIndex ).russians[c] = "";
	}

	// assign to russians
	for(size_t c=0; c<lines.size(); c++)
	{

		this->m_dictWords->at( (size_t)engWordIndex  ).russians[c] = lines[c].c_str();
	}

 

	return true;
}

bool Dictionary::DeleteWordIndex( const int engWordIndex)
{
	if( (size_t)engWordIndex >= m_dictWords->size() )
	{
		// нет такого слова
		return false;
	}

	m_dictWords->erase( m_dictWords->begin() + (size_t)engWordIndex  );
	SortWords();


	return true;
}

static bool ___SortDictWords( const dictionaryWord& a1, const dictionaryWord& a2 )
{
	if( a1.english_word < a2.english_word ) return true;
	return false;
}

void Dictionary::SortWords()
{
	std::sort( m_dictWords->begin(), m_dictWords->end(),  ___SortDictWords);
}




